package service.calculator.bonchon;

import java.math.BigDecimal;

import models.Payment;
import models.Rate;
import service.BillingCalculator;
import util.Rounder;

public class BonchonBillingCalculatorImpl implements BillingCalculator {

    public BigDecimal calculatePayment(Rate rate, Payment payment) {
        BigDecimal paymentCalculation = null;
        BonchonPaymentType paymentType = BonchonPaymentType
                .valueOf(payment.paymentType);
        BigDecimal paymentHrs = BigDecimal.valueOf(payment.hours);

        switch (paymentType) {
        case BASIC:
        	BigDecimal basicBillingRate = calculateBasicBillingRate(rate);
            paymentCalculation = basicBillingRate.multiply(paymentHrs);
            break;
        case HP:
        case RDRT:
            BigDecimal hpRate = rate.value.add(rate.value.multiply(BigDecimal.valueOf(0.30)));
            paymentCalculation = hpRate.multiply(paymentHrs);
            break;
        case HPU:
        case LHRT:
        	paymentCalculation = rate.value.multiply(paymentHrs);
            break;
        case OT:
            BigDecimal otRate = rate.value.add(rate.value.multiply(BigDecimal.valueOf(0.25)));
            paymentCalculation = otRate.multiply(paymentHrs);
            break;
        case LHOT:
            BigDecimal lhotRate = rate.value.add(rate.value.multiply(BigDecimal.valueOf(1)));
            lhotRate = lhotRate.add(lhotRate.multiply(BigDecimal.valueOf(0.30)));
            paymentCalculation = lhotRate.multiply(paymentHrs);
            break;
        case SHRT:
            BigDecimal shrtRate = rate.value.multiply(BigDecimal.valueOf(0.30));
            paymentCalculation = shrtRate.multiply(paymentHrs);
            break;
        case SHOT:
        case RDOT:
            BigDecimal shotRate = rate.value.multiply(BigDecimal.valueOf(1.3));
            shotRate = shotRate.add(shotRate.multiply(BigDecimal.valueOf(0.30)));
            paymentCalculation = shotRate.multiply(paymentHrs);
            break;
        case RDLH:
            BigDecimal rdlhRate = rate.value.add(rate.value.multiply(BigDecimal.valueOf(1.6)));
            paymentCalculation = rdlhRate.multiply(paymentHrs);
            break;
        case RDSH:
        	BigDecimal rdshRate = rate.value.add(rate.value.multiply(BigDecimal.valueOf(0.60)));
            paymentCalculation = rdshRate.multiply(paymentHrs);
            break;
        case NDRT:
            BigDecimal ndrtRate = rate.value.multiply(BigDecimal.valueOf(0.1001));
            paymentCalculation = ndrtRate.multiply(paymentHrs);
            break;
        case NDLH:
        	BigDecimal ndlhRate = rate.value.multiply(BigDecimal.valueOf(0.20));
            paymentCalculation = ndlhRate.multiply(paymentHrs);
            break;
        case NDSH:
        	BigDecimal ndshRate = rate.value.multiply(BigDecimal.valueOf(0.13));
            paymentCalculation = ndshRate.multiply(paymentHrs);
            break;
        case TRANSPO:
            // This is money value already
            paymentCalculation = paymentHrs;
            break;
        case ECOLA:
            paymentCalculation = BigDecimal.valueOf(1.875).multiply(paymentHrs);
            break;
        case SEA:
            paymentCalculation = BigDecimal.valueOf(1.625).multiply(paymentHrs);
            break;
        default:
            System.out.println("WARNING: " + payment.paymentType
                    + " payment type not yet supported.");
        }

        if (paymentCalculation != null) {
        	paymentCalculation = Rounder.roundup(paymentCalculation);
        }

        return paymentCalculation;
    }

	private BigDecimal calculateBasicBillingRate(Rate rate) {
		/*
		 * Basic per hour = 426/8
		 * Basic + (Basic * 0.08) = 57.51
		 */
		BigDecimal basicBillingRate = rate.value.add(rate.value.multiply(BigDecimal.valueOf(0.08)));

		BigDecimal governmentBenefits = computeGovernmentBenefitsPerHour();
      	basicBillingRate = basicBillingRate.add(governmentBenefits);

		return basicBillingRate;
	}

	protected BigDecimal computeGovernmentBenefitsPerHour() {
		// Per day is computed by monthly/26 days.
		BigDecimal thirteenthMonthPayPerDay = BigDecimal.valueOf(37.58);
		BigDecimal sssPerDay = BigDecimal.valueOf(31.65);
		BigDecimal philhealthPerDay = BigDecimal.valueOf(5.60);
		BigDecimal pagIbigPerDay = BigDecimal.valueOf(3.85);
		BigDecimal ecMcPerDay = BigDecimal.valueOf(0.38);

		BigDecimal governmentBenefits = BigDecimal.valueOf(0.00);
		governmentBenefits = governmentBenefits.add(thirteenthMonthPayPerDay);
		governmentBenefits = governmentBenefits.add(sssPerDay);
		governmentBenefits = governmentBenefits.add(philhealthPerDay);
		governmentBenefits = governmentBenefits.add(pagIbigPerDay);
		governmentBenefits = governmentBenefits.add(ecMcPerDay);

		// Compute per hour
		governmentBenefits = governmentBenefits.divide(BigDecimal.valueOf(8));

		return governmentBenefits;
	}

}
